feat: add editor multiline mode and many edge case fixes#476
Merged
Conversation
Prevents mobile voice recording glitch where holding the record button would select text from the 'following the conversation' row underneath.
When recording on mobile, if the pointerup listener was lost (e.g., dragging off the button), there was no way to stop recording. Now the stop button's onClick handler works on mobile when recording is active, providing a fallback.
…ecording Prevents layout shift by rendering the recorder in the editor's main content area instead of in the after buttons section. Uses replacementContent prop to swap the editor with the recorder while maintaining proper padding.
7078f73 to
f22a764
Compare
Contributor
functional testingfunctions well:
couldn't be tested rn:
|
dozro
approved these changes
Mar 22, 2026
Contributor
Deploying with
|
| Status | Preview URL | Commit | Alias | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! | https://pr-476-sable.raspy-dream-bb1d.workers.dev | e5d5230 | pr-476 |
Sun, 22 Mar 2026 18:21:53 GMT |
dozro
approved these changes
Mar 22, 2026
7w1
approved these changes
Mar 23, 2026
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 24, 2026
> [!IMPORTANT] > Merging this PR will create a new release. ## Features * `Ctrl + K` search menu is now context aware and lists the current space's rooms at the top. ([#499](#499) by @7w1) * Add knocking support when attempting to join a room from the directory, an address, a room mention, or space hierarchy, as well as text command support for knocking. Also improves rendering for knock notifications in rooms. ([#470](#470) by @polyjitter) * Add Android/iOS PWA-specific icon variants. ([#473](#473) by @Septicity) * Add support for youtube embeds. ([#497](#497) by @thundertheidiot) * Add sidebar three dot menu for quick access to related settings ([#474](#474) by @wolterkam) * Replies that mention the OP are now indicated by the OP username being prefixed with @ ([#465](#465) by @mini-bomba) * Made pin events show a tally of the messages that are pinned. ([#462](#462) by @nushea) ### Improve multiline composer and voice recording ([#476](#476) by @hazre) - Add a multiline composer layout for longer drafts. - Keep the voice recorder between composer actions in multiline mode. - Show the recorder inside the composer on mobile while recording. - Prevent the composer from expanding when recording starts. - Make the recorder footer and waveform fit better across screen sizes. - Let interrupted mobile recording gestures still stop correctly. - Stabilize wrap detection around edge cases like narrow widths and trailing spaces. ## Fixes * Added error messages provided by homeserver to unknown login errors. ([#496](#496) by @7w1) * Ensure new updates always reload the page properly. ([#502](#502) by @7w1) * Removed the blocked users moved notice from notifications setting page. ([#490](#490) by @7w1) * Fix recieved encrypted message per-message profiles not triggering rerenders. ([#464](#464) by @7w1) * Add `.m4a` files as a recognized audio type. ([#472](#472) by @henk717) * Fix messages disappearing from rooms after reconnects and timeline resets. ([#478](#478) by @hazre) * Fix Camera being enabled by default even when the client has it off pre joining in browsers that permit the video (Electron/Tauri as examples). ([#485](#485) by @Rawrington) * Fix cinny-dark-theme link colors being too dark ([#469](#469) by @Elec3137) * Fix "Default" menu item height in room notification switcher. ([#466](#466) by @polyjitter) * fix the issue of empty displaynames of a persona, causing an empty fallback message, it will now ommit the fallback, if the name is empty or only consists of whitespace ([#495](#495) by @dozro) * Fixed an Android issue where recording a voice message with headphones could leave audio stuck in low-quality mode until the app was restarted. ([#476](#476) by @hazre) * Fixed voice message scrubbing/seeking on Firefox by switching the recorder from WebM (no seek index) to Ogg/Opus. ([#476](#476) by @hazre) * fixes touchpad zooming behaviour ([#481](#481) by @integralfunction) * Fixes width mismatch for the call chat view. ([#460](#460) by @polyjitter) * Fix messages sent from sable showing wrong on other client(s) ([#468](#468) by @nushea) ## Documentation * Updated PR template and CONTRIBUTING.md to add AI disclosure requirement. ([#456](#456) by @Rosy-iso)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #350
This adds a dynamic multiline layout to
CustomEditor. When the message input grows past a single line (word wrap, explicit newlines, or multiple blocks), the editor shifts from a single-row layout into a two-row grid, before/textarea on top, with responsive content spanning the full width below. It drops back to single-row once the text fits on one line again.The old
replacementContentprop (which swapped out the textarea on mobile during voice recording) is gone. It's replaced byresponsiveAfter, which renders inline next to the send button in single-line mode and moves down to the footer row in multiline mode. There's also aforceMultilineLayoutprop for when you want to push into multiline immediately, which is what we use when the audio recorder opens. This means the recorder now takes the same code path on desktop and mobile instead of having a separate mobile-only branch.A few other things got fixed along the way:
userSelect: none. (related to voice message recording not possible on phone bc ui design #350)onClickwas being skipped on mobile entirely, so ifpointerupgot lost mid-drag there was no way to stop recording. NowonClickworks as a fallback when recording is already active. (a form of recovery in case more situations like voice message recording not possible on phone bc ui design #350 happen again)ResizeObserverinstead of a hardcoded number.cleanupMediaRecorderwasn't being called in all the stop/delete/restart/error/unmount paths, which could leave the mic track open. That's fixed.audio/webmdoesn't include a seek index. Codec preference now putsaudio/ogg;codecs=opusfirst so Firefox records seekable blobs. Also added aseekTohelper that waits forloadedmetadataif the audio element isn't ready yet, andaudio.preload = 'auto'+audio.load()on mount so Firefox parses metadata right away.requestAnimationFrameand uses aResizeObserveron the scroll container to cut down on flicker and extra re-renders.Also sorry for the cursed line height measurer, there was legit no other way to detect it that didn't cause other issues.
Good amount of this was created with help of AI (like figuring out options on how to fix the edge cases), especially the edge case unit tests, but It had to be fixed by hand in many places and frankly I can't tell you exactly where was what. I've been working on this for couple days now.. (losing my mind over it)
Screenshots:
Recording.2026-03-22.182018.mp4
Recording.2026-03-22.182144.mp4
Type of change
Checklist:
AI disclosure: